#include "gui.h"
#include "oled.h"
#include "font.h"
#include "color.h"
#include "String.h"


extern OLED_INFO oled_info;
extern u16 FRONT_COLOR;	//画笔颜色
extern u16 BACK_COLOR;  //背景色
u8 row_num;
char printf_buff[PRINTF_BUFF];

/*****************************************************************************
 * @name       :void GUI_DrawPoint(u16 x,u16 y,u16 color)
 * @date       :2021.6.6 
 * @function   :简单设置坐标颜色
 * @param 		 :u8 x			x的坐标
 * @param 		 :u8 y			y的坐标
 * @param 		 :u16 color 		颜色数据
 * @retvalue   :None
******************************************************************************/
void GUI_DrawColorPoint(u8 x,u8 y,u16 color)
{
	OLED_SetColorDraw(x,y,color);
}
/*****************************************************************************
 * @name       :void GUI_DrawPoint(u16 x,u16 y)
 * @date       :2021.6.6 
 * @function   :快速画点
 * @param 		 :u8 x			x的坐标
 * @param 		 :u8 y			y的坐标
 * @retvalue   :None
******************************************************************************/
void GUI_DrawPoint(u8 x,u8 y)
{
	OLED_SetDraw(x,y);
}
/*****************************************************************************
 * @name       :void GUI_Fill(u8 startx,u8 starty,u8 endx,u8 endy,u16 color)
 * @date       :2021.6.6 
 * @function   :指定位置指定颜色画框
 * @param 		 :u8 startx			开始x的坐标
 * @param 		 :u8 starty			开始y的坐标
 * @param 		 :u8 endx				结束x的坐标
 * @param 		 :u8 endy				结束y的坐标
 * @param 		 :u16 color 		颜色数据
 * @retvalue   :None
******************************************************************************/
void GUI_Fill(u8 startx,u8 starty,u8 endx,u8 endy,u16 color)
{
	u8 line,row,width,height;
	width = endx - startx+1;
	height = endy - starty +1;
	OLED_SetWindows(startx,starty,endx,endy);
	for(line = 0;line<width;line++)
	{
		for(row = 0;row<height;row++)
		{
			OLED_WriteData16Bit(color);
		}
	}
}
/*****************************************************************************
 * @name       :void GUI_DrawLine(u8 startx,u8 starty,u8 endx,u8 endy,u16 color)
 * @date       :2021.6.6 
 * @function   :指定位置指定颜色画线
 * @param 		 :u8 startx			开始x的坐标
 * @param 		 :u8 starty			开始y的坐标
 * @param 		 :u8 endx				结束x的坐标
 * @param 		 :u8 endy				结束y的坐标
 * @param 		 :u16 color 		颜色数据
 * @retvalue   :None
******************************************************************************/
void GUI_DrawLine(u8 startx,u8 starty,u8 endx,u8 endy,u16 color)
{
		u8 num; 
	int xerr=0,yerr=0,delta_x,delta_y,distance; 
	int incx,incy,uRow,uCol; 
	
	delta_x=endx-startx; //计算坐标增量 
	delta_y=endy-starty; 
	uRow=startx; 
	uCol=starty; 
	if(delta_x>0)incx=1; //设置单步方向 
	else if(delta_x==0)incx=0;//垂直线 
	else {incx=-1;delta_x=-delta_x;} 
	if(delta_y>0)incy=1; 
	else if(delta_y==0)incy=0;//水平线 
	else{incy=-1;delta_y=-delta_y;} 
	if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
	else distance=delta_y; 
	for(num = 0;num <= distance+1;num++ )//画线输出 
	{  
		GUI_DrawColorPoint(uRow,uCol,color);//画点 
		xerr+=delta_x ; 
		yerr+=delta_y ; 
		if(xerr>distance) 
		{ 
			xerr-=distance; 
			uRow+=incx; 
		} 
		if(yerr>distance) 
		{ 
			yerr-=distance; 
			uCol+=incy; 
		} 
	}
}
/*****************************************************************************
 * @name       :void GUI_DrawRound(int Center_X, int Center_y,u8 x,u8 y)
 * @date       :2021.6.6 
 * @function   :画圆
 * @param 		 :int Center_X			圆心x的坐标
 * @param 		 :int Center_y			圆心y的坐标
 * @param 		 :u8 x				相对于圆心的x坐标
 * @param 		 :u8 y				相对于圆心的y坐标
 * @retvalue   :None
******************************************************************************/
void GUI_DrawRound(int Center_X, int Center_y,u8 x,u8 y)
{
	GUI_DrawColorPoint(Center_X + x, Center_y + y, FRONT_COLOR);

	GUI_DrawColorPoint(Center_X - x, Center_y + y, FRONT_COLOR);

	GUI_DrawColorPoint(Center_X + x, Center_y - y, FRONT_COLOR);

	GUI_DrawColorPoint(Center_X - x, Center_y - y, FRONT_COLOR);

	GUI_DrawColorPoint(Center_X + y, Center_y + x, FRONT_COLOR);

	GUI_DrawColorPoint(Center_X - y, Center_y + x, FRONT_COLOR);

	GUI_DrawColorPoint(Center_X + y, Center_y - x, FRONT_COLOR);

	GUI_DrawColorPoint(Center_X - y, Center_y - x, FRONT_COLOR);
}

/*****************************************************************************
 * @name       :void GUI_circle(int Center_X, int Center_Y,int r, int fill)
 * @date       :2021.6.6 
 * @function   :在指定的位置画一个指定大小的圆
 * @parame		 :int Center_X		圆心x的坐标
 * @param			 :int Center_Y		圆心x的坐标 
 * @param			 :int r						圆的半径
 * @param			 :int fill				是否填充
 *				@arg		1-填充
 *				@arg		0-不填充														
 * @retvalue   :None
******************************************************************************/  
void GUI_circle(int Center_X, int Center_Y,int r, int fill)
{
	int x = 0, y = r, yi, d;

	d = 3 - 2 * r;


	if (fill) 
	{
		// 如果填充（画实心圆）
		while (x <= y) {
			for (yi = x; yi <= y; yi++)
				GUI_DrawRound(Center_X, Center_Y, x, yi);

			if (d < 0) {
				d = d + 4 * x + 6;
			} else {
				d = d + 4 * (x - y) + 10;
				y--;
			}
			x++;
		}
	} else 
	{
		// 如果不填充（画空心圆）
		while (x <= y) {
			GUI_DrawRound(Center_X, Center_Y, x, y);
			if (d < 0) {
				d = d + 4 * x + 6;
			} else {
				d = d + 4 * (x - y) + 10;
				y--;
			}
			x++;
		}
	}
}
/*****************************************************************************
 * @name       :void GUI_ShowChar(u16 x,u16 y,u16 fc,u16 bc,char num,u8 size,u8 mode)
 * @date       :2021.6.6 
 * @function   :在指定位置显示指定颜色的字符
 * @parame		 :u16 x		x的坐标
 * @param			 :u16 y		x的坐标 
 * @param			 :u16 fc	画笔颜色
 * @parame		 :u16 bc		背景颜色
* @param			 :char num		要显示的字符 
 * @param			 :u8 size	文字大小(12,16号字体)
 * @param			 :u8 mode		是否叠加
 *				@arg		1-填充
 *				@arg		0-不填充														
 * @retvalue   :None
******************************************************************************/
void GUI_ShowChar(u16 x,u16 y,u16 fc,u16 bc,char num,u8 size,u8 mode)
{
	u8 temp;
  u8 pos,t;   
	
	num=num-' ';//得到偏移后的值
	OLED_SetWindows(x,y,x+size/2-1,y+size-1);//设置单个文字显示窗口
	if(!mode) //非叠加方式
	{		
		for(pos=0;pos<size;pos++)
		{
			if(size==12)temp=ascii_1206[num][pos];//调用1206字体
			else temp=ascii_1608[num][pos];		 //调用1608字体
			for(t=0;t<size/2;t++)
			{                 
				if(temp&0x01)
				{
					OLED_WriteData16Bit(fc); 
				}
				else 
				{
					OLED_WriteData16Bit(bc); 
				}
				temp>>=1; 
			}
		}	
	}else//叠加方式
	{
		for(pos=0;pos<size;pos++)
		{
			if(size==12)temp=ascii_1206[num][pos];//调用1206字体
			else if(size==16) temp=ascii_1608[num][pos];		 //调用1608字体
			
			for(t=0;t<size/2;t++)
			{             
					if(temp&0x01)GUI_DrawColorPoint(x+t,y+pos,fc);//画一个点    
					temp>>=1; 
			}
		}
	}	
	OLED_SetWindows(0,0,oled_info.OLED_Width-1,oled_info.OLED_Hight-1);//恢复窗口为全屏
}

/*****************************************************************************
 * @name       :u8 GUI_ShowString(u16 x,u16 y,u8 size,u8 len,u8 mode,char *p)
 * @date       :2021.6.6 
 * @function   :在指定位置显示指定颜色的字符
 * @parame		 :u16 x		x的坐标
 * @param			 :u16 y		x的坐标 
 * @param			 :u8 size	文字大小(12,16号字体)
 * @parame		 :u8 len 没用
 * @param			 :u8 mode		是否叠加
 *				@arg		1-填充
 *				@arg		0-不填充
 * @param			 :char *p		要显示的字符串											
 * @retvalue   :None
******************************************************************************/
void GUI_ShowString(u16 x,u16 y,u8 size,u8 len,u8 mode,char *p)
{   
    while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
    {   
			if(y>(oled_info.OLED_Hight-1))		//超出边界了 
				return ; 
			if(x>(oled_info.OLED_Width-1))
			{
				x = 0;
				y += 12;
				row_num++;
			}
			GUI_ShowChar(x,y,FRONT_COLOR,BACK_COLOR,*p,size,mode);
			x += size/2;		//设置下一个窗口的x坐标
			p += 1;
    }
		row_num++;
}
/*****************************************************************************
 * @name       :u32 GUI_pow(u8 m,u8 n)
 * @date       :2021.6.6 
 * @function   :求m^n
 * @parame		 :u8 m 	数值
 * @param			 :u8 n  数值										
 * @retvalue   :返回为求m^n的值
******************************************************************************/
u32 GUI_pow(u8 m,u8 n)
{
	u32 result=1;	 
	while(n--)result*=m;    
	return result;
}

/*****************************************************************************
 * @name       :void GUI_ShowNum(u16 x,u16 y,u8 size,u8 len,u8 mode,u32 num)
 * @date       :2021.6.6 
 * @function   :在指定位置显示指定颜色的数值
 * @parame		 :u16 x		x的坐标
 * @param			 :u16 y		x的坐标 
 * @param			 :u8 size	文字大小(12,16号字体)
 * @parame		 :u8 len 长度
 * @param			 :u8 mode		是否叠加
 *				@arg		1-填充
 *				@arg		0-不填充
 * @param			 :u32 num		要显示的数值										
 * @retvalue   :None
******************************************************************************/
void GUI_ShowNum(u16 x,u16 y,u8 size,u8 len,u8 mode,u32 num)
{         	
	u8 t,temp;
	u8 enshow=0;						    
	for(t=0;t<len;t++)
	{
		temp=(num/GUI_pow(10,len-t-1))%10;
		if(enshow==0&&t<(len-1))
		{
			if(temp==0)
			{
				GUI_ShowChar(x+(size/2)*t,y,FRONT_COLOR,BACK_COLOR,' ',size,mode);
				continue;
			}else enshow=1; 
		 	 
		}
	 	GUI_ShowChar(x+(size/2)*t,y,FRONT_COLOR,BACK_COLOR,temp+'0',size,mode); 
	}
}
/*****************************************************************************
 * @name       :void GUI_ShowStrMiddle(u8 x,u8 y,char *str,u8 size,u8 mode)
 * @date       :2021.6.6 
 * @function   :在指定位置显示指定颜色的数值
 * @parame		 :u16 x		居中x的坐标
 * @param			 :u16 y		居中y的坐标 
 * @param			 :char *str		要显示的字符串
 * @param			 :u8 size	文字大小(12,16号字体)
 * @param			 :u8 mode		是否叠加
 *				@arg		1-填充
 *				@arg		0-不填充							
 * @retvalue   :None
******************************************************************************/
void GUI_ShowStrMiddle(u8 x,u8 y,char *str,u8 size,u8 mode)
{
		u16 len=strlen((const char *)str);
		u16 x1=(oled_info.OLED_Width-len*8)/2;
		GUI_ShowString(x1,y,size,0,mode,str);
}

/*****************************************************************************
 * @name       :void GUI_Button(u8 x,u8 y,u8 highly,u8 len,u8 mode)
 * @date       :2021.6.6 
 * @function   :按钮
 * @parame		 :u16 x		x的坐标
 * @param			 :u16 y		y的坐标 
 * @param			 :u8 highly		按钮的高度
 * @param			 :u8 len	按钮的宽度
 * @param			 :u8 mode		是否叠加
 *				@arg		1-填充
 *				@arg		0-不填充							
 * @retvalue   :None
******************************************************************************/
void GUI_Button(u8 x,u8 y,u8 highly,u8 len,u8 mode)
{
	if(!mode)
	{
		GUI_Fill(x,y,x+len,y+highly,FRONT_COLOR);
		GUI_DrawLine(x,y+highly,x+len+1,y+highly+1,LightGray);//LightGray
		GUI_DrawLine(x+len,y,x+len+1,y+highly,LightGray);
	}
	else
	{
		GUI_Fill(x,y,x+len,y+highly,FRONT_COLOR);
	}
}
/*****************************************************************************
 * @name       :void GUI_ButtStrMiddle(u8 x,u8 y,u8 highly,u8 len,u8 Butt_mode,u8 size,char *str,u8 Str_mode)
 * @date       :2021.6.6 
 * @function   :按钮居中显示字符串
 * @parame		 :u16 x		x的坐标
 * @param			 :u16 y		y的坐标 
 * @param			 :u8 highly		按钮的高度
 * @param			 :u8 len	按钮的宽度
 * @param			 :u8 Butt_mode		是否叠加
 *				@arg		1-填充
 *				@arg		0-不填充
 * @param			 :u8 size		字符的大小
 * @param			 :char *str		字符串
 * @param			 :u8 Str_mode	字符模式
 *				@arg		1-填充
 *				@arg		0-不填充
 * @retvalue   :None
******************************************************************************/
//按钮居中显示字符串
void GUI_ButtStrMiddle(u8 x,u8 y,u8 highly,u8 len,u8 Butt_mode,u8 size,char *str,u8 Str_mode)
{
	u16 str_len=strlen((const char *)str);
	u8 x1;
	if (str_len % 2 == 0)
	{
			if(((len)/2 %2) == 0)
			{
				x1 = x+((len)/2)-((str_len*size/2/2));
			}
			else
			{
				x1 = x+((len)/2+1)-((str_len*size/2/2));
			}
	}
	else
	{
			if(((len)/2 %2) == 0)
			{
				x1 = x+((len)/2)-((str_len*size/2/2+1));
			}
			else
			{
				x1 = x+((len)/2+1)-((str_len*size/2/2+1));
			}
	}		
	if(x1-x>len)
	{
		return ;
	}
	GUI_Button(x,y,highly,len,Butt_mode);
	u16 color_temp = FRONT_COLOR;
	FRONT_COLOR = BLACK;
	GUI_ShowString(x1,y+2,size,1,Str_mode,str);
	 FRONT_COLOR = color_temp;
}
/*****************************************************************************
 * @name       :void Clear_1608Map(void)
 * @date       :2021.6.6 
 * @function   :清除行标志
 * @parame		 :None
 * @retvalue   :None
******************************************************************************/
void Clear_1608Map(void)
{
	row_num = 0;
}
/*****************************************************************************
 * @name       :void GUI_Printf(char *str)
 * @date       :2021.6.6 
 * @function   :显示字符串(最多显示10行,每行最多显示16个英文字母)
 * @param			 :char *str		字符串
 * @retvalue   :None
******************************************************************************/
void GUI_Printf(char *str)
{
	u8 size = 16;
	u8 x = 0,y = 0;
	//判断是否超出边界线
	if(13*row_num > oled_info.OLED_Hight)
		return ;
	if(x>(oled_info.OLED_Hight-1))		//超出边界了 
	{
		x = 0;
		y += 12;
		row_num ++;
	}
	x = 0;
	y = 13*row_num;
//void GUI_ShowString(u16 x,u16 y,u8 size,u8 len,u8 mode,char *p);//显示字符串
	GUI_ShowString(x,y,size,0,1,str);
}

/*****************************************************************************
 * @name       :void Set_Buff(char *str,...)
 * @date       :2021.6.6 
 * @function   :设置字符缓冲区
 * @param			 :char *str		字符串
 * @retvalue   :None
******************************************************************************/
void Set_Buff(char *str)
{
	u8 Str_len = strlen((const char *)str);
	u8 Set_BuffNum;
	for(Set_BuffNum = 0;Set_BuffNum < Str_len;Set_BuffNum++)
	{
			printf_buff[Set_BuffNum] = *str;
			str ++;
			//printf_buff[i] = (char)num;
	}
}
